package cate.game.role.chat;

import cate.common.game.GameCollection;
import cate.common.table.d.GDChat;
import cate.common.util.GameResult;
import cate.game.chat.*;
import cate.game.chat.msg.MyChatDataResp;
import cate.game.chat.msg.MyLastChatTimeResp;
import cate.game.role.Role;
import cate.game.role.RolePart;
import cate.game.util.api.ChatApi;
import easy.java.dev.note.NoteField;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.List;

@Document(collection = GameCollection.NAME_ROLE_CHAT)
public class RoleChat extends RolePart {
    @NoteField(value = "上次发言时间")
    public long lastChatTime;

    @NoteField(value = "禁言截止时间")
    public long forbidUntil;

    @NoteField(value = "禁言原因")
    public String forbidReason;

    @NoteField("聊天发言次数")
    public int chatTimes;

    public RoleChat() {

    }

    public RoleChat(Role role) {
        super(role);
    }

    /**
     * 是否允许发言
     */
    private boolean allow() {
        return System.currentTimeMillis() > forbidUntil;
    }

    public void forbidAdd(long addMs) {
        long now = System.currentTimeMillis();
        if (forbidUntil < now) {
            forbidUntil = now;
        }
        forbidUntil += addMs;
    }

    public void handleForbid(long forbidUntil, String forbidReason) {
        this.forbidUntil = forbidUntil;
        this.forbidReason = forbidReason;
        role.sendNow(new MyChatDataResp(role));
    }

    private GameResult<Void> preChatCheck(byte channel, String content) {
        GameResult<Void> r = new GameResult<>();
        if (!allow()) {
            return r.fail( "您被禁止发言");
        }
        if (StringUtils.isBlank(content)) {
            return r.fail( "聊天内容不能为空");
        }
        // 聊天等级限制
        int levelRequired = role.getGame().table.chat.level.getLevelByChannel(channel, role.getGame().status.getOpenDay());
        if (role.getBase().level < levelRequired) {
            return r.fail( "{}级后才能在此频道发言", levelRequired);
        }
        // 聊天间隔限制
        long chatInterval = System.currentTimeMillis() - lastChatTime;
        long timeRemaining = (GDChat.CHAT_INTERVAL - chatInterval) / 1000;
        if (timeRemaining > 0) {
            return r.fail( "发言太快了，{}秒后再尝试", timeRemaining);
        }
        return r;
    }

    public void sendPrivate(String toId, int contentId, String content, List<ChatContentParam> params) {
        GameResult<Void> r = new GameResult<>();
        if (StringUtils.isNotBlank(content)) {
            r = preChatCheck(GDChat.Channel.PRIVATE, content);
        } else if (contentId <= 0) {
            return;
        }
        if (!r.ok()) {
            role.getGame().notice.message(role, r);
            return;
        }
        if (role.getFriend().inBlackList(toId)) {
            role.getGame().notice.message(role, "您已经将其拉黑，无法对其发起私聊");
            return;
        }
        lastChatTime = System.currentTimeMillis();
        role.getGame().chat.sendPrivate(role, toId, contentId, role.getGame().tools.sensitiveWords.replace(content), params);
        role.sendNow(new MyLastChatTimeResp(lastChatTime, chatTimes));
    }

    public void sendPublic(ChatRequest request) {
        GameResult<Void> r;
        if (StringUtils.isBlank(request.content)) {
            r = new GameResult<>();
        } else {
            r = preChatCheck(request.channel, request.content);
        }
        if (!r.ok()) {
            role.getGame().notice.message(role, r);
            return;
        }
        lastChatTime = System.currentTimeMillis();
        chatTimes ++;
        // 下面根据不同频道执行不同的发送逻辑
        ChatThread.exe(() -> {
            GameResult<String> rApi = ChatApi.checkPublic(role, request.content, request.channel);
            if(!rApi.ok()) {
                role.getGame().notice.message(role, rApi);
                return;
            }
            chatExe(request.channel, request.contentId, request.content, request.params);
            if (request.channel == GDChat.Channel.WORLD) {
                role.getHistory().action.sendWorldMsg();
            }
        });

        role.getTrace().addPublicChat();
        role.sendNow(new MyLastChatTimeResp(lastChatTime, chatTimes));
    }

    private void chatExe(byte channel, int contentId, String content, List<ChatContentParam> params) {
        switch (channel) {
            case GDChat.Channel.GROUP:
                sendGroup(role, contentId, content, params);
                break;
            case GDChat.Channel.CROSS:
                sendCross(role, contentId, content, params);
                break;
            case GDChat.Channel.ELITE_RACE:
                sendEliteRace(role, contentId, content, params);
                break;
            case GDChat.Channel.CHAMPION_RACE:
                sendChampionRace(role, contentId, content, params);
                break;
            case GDChat.Channel.ZONE_DWS:
            case GDChat.Channel.ZONE_CHAMPION:
            case GDChat.Channel.THRONE_BATTLE:
                sendZone(channel, role, contentId, content, params);
                break;
            default:
                sendLocal(channel, contentId, content, params);
                break;
        }
    }

    private void sendGroup(Role role, int contentId, String content, List<ChatContentParam> params) {
        ChatPublicItem item = new ChatPublicItem(role, GDChat.Channel.GROUP, contentId, content, params);
        role.getGame().chat.sendGroup(item);
    }

    private void sendCross(Role role, int contentId, String content, List<ChatContentParam> params) {
        ChatPublicItem item = new ChatPublicItem(role, GDChat.Channel.CROSS, contentId, content, params);
        role.getGame().chat.sendCross(item);
    }

    private void sendEliteRace(Role role, int contentId, String content, List<ChatContentParam> params) {
        role.getHistory().action.eliteRaceChatTimes();
//        boolean isRemote = role.getGame().pvp.eliteRace.getDataManager().isRemoteSeasonOpen();
//        if (isRemote) {
//            role.getGame().chat.sendCross(new ChatPublicItem(role, GDChat.Channel.ELITE_RACE, contentId, content, params));
//        } else {
            sendLocal(GDChat.Channel.ELITE_RACE, contentId, content, params);
//        }
    }

    private void sendChampionRace(Role role, int contentId, String content, List<ChatContentParam> params) {
        role.getGame().chat.sendCross(new ChatPublicItem(role, GDChat.Channel.CHAMPION_RACE, contentId, content, params));;
    }

    private void sendZone(byte channel, Role role, int contentId, String content, List<ChatContentParam> params) {
        ChatPublicItem item = new ChatPublicItem(role, channel, contentId, content, params);
        role.getGame().chat.sendGroup(item);
    }

    // 发送本服聊天
    private void sendLocal(byte channel, int contentId, String content, List<ChatContentParam> params) {
        ChatFacade.sendPublicFromClient(role, channel, contentId, content, params);
    }
}
